from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Iterable, List, Sequence

from agent_society.memory.event_log import Event, append_event, read_events

TASK_EVENT = "gov_task"
COMMENT_EVENT = "gov_task_comment"
UPDATE_EVENT = "gov_task_update"


@dataclass(slots=True)
class TaskSummary:
    id: str
    title: str
    status: str
    assignees: str
    created_at: str
    actor: str
    description: str


def create_task(
    base_dir: Path,
    owner: str,
    actor: str,
    title: str,
    description: str,
    assignees: Sequence[str] | None = None,
) -> Event:
    headers = {"title": title, "status": "open"}
    if assignees:
        headers["assignees"] = ",".join(sorted({a.strip() for a in assignees if a.strip()}))
    return append_event(base_dir, owner, actor, TASK_EVENT, description, headers)


def add_comment(
    base_dir: Path,
    owner: str,
    actor: str,
    task_id: str,
    message: str,
) -> Event:
    headers = {"in_reply_to": task_id}
    return append_event(base_dir, owner, actor, COMMENT_EVENT, message, headers)


def update_status(
    base_dir: Path,
    owner: str,
    actor: str,
    task_id: str,
    status: str,
) -> Event:
    headers = {"in_reply_to": task_id, "status": status}
    return append_event(base_dir, owner, actor, UPDATE_EVENT, "", headers)


def list_tasks(
    base_dir: Path,
    owner: str,
    *,
    assignee: str | None = None,
    status: str | None = None,
) -> List[TaskSummary]:
    events = read_events(base_dir, owner)
    tasks = [e for e in events if e.type == TASK_EVENT]
    summaries: List[TaskSummary] = []
    for task in sorted(tasks, key=lambda e: e.created_at, reverse=True):
        assignees = task.headers.get("assignees", "")
        if assignee and assignee not in assignees.split(","):
            continue
        effective_status = _effective_status(events, task)
        if status and effective_status != status:
            continue
        summaries.append(
            TaskSummary(
                id=task.id,
                title=task.headers.get("title", ""),
                status=effective_status,
                assignees=assignees,
                created_at=task.created_at,
                actor=task.actor,
                description=task.content,
            )
        )
    return summaries


def _effective_status(events: Iterable[Event], task: Event) -> str:
    current = task.headers.get("status", "open")
    updates = [e for e in events if e.type == UPDATE_EVENT and e.headers.get("in_reply_to") == task.id]
    if not updates:
        return current
    updates.sort(key=lambda e: e.created_at)
    return updates[-1].headers.get("status", current)
